package com.ruoyi.common.redis.configure;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;
import com.ruoyi.common.core.constant.Constants;
import org.springframework.util.ObjectUtils;

/**
 * Redis使用FastJson序列化
 *
 * @author ruoyi
 */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    // 增强白名单过滤（防止反序列化漏洞）
    static final Filter AUTO_TYPE_FILTER;

    static {
        // 处理基础白名单（兼容可能为null或空字符串的情况）
        List<String> whitelistList = new ArrayList<>();

        // 常量是数组类型，直接遍历添加
        if (!ObjectUtils.isEmpty(Constants.JSON_WHITELIST_STR)) {
            for (String item : Constants.JSON_WHITELIST_STR) {
                if (item != null) {
                    // 对数组中的每个元素进行trim处理
                    String trimmed = trimString(item);
                    if (!trimmed.isEmpty()) {
                        whitelistList.add(trimmed);
                    }
                }
            }
        }

        // 添加自定义包前缀
        String[] customWhitelist = {"com.ruoyi.", "java.lang.", "java.util."};
        whitelistList.addAll(Arrays.asList(customWhitelist));

        // 转换为数组并去重
        String[] allWhitelist = whitelistList.stream()
                .distinct()
                .toArray(String[]::new);

        AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(allWhitelist);
    }

    // 手动实现字符串trim功能（去除首尾空格）
    private static String trimString(String str) {
        if (str == null || str.isEmpty()) {
            return "";
        }
        int start = 0;
        int end = str.length() - 1;
        // 找到第一个非空格字符的位置
        while (start <= end && Character.isWhitespace(str.charAt(start))) {
            start++;
        }
        // 找到最后一个非空格字符的位置
        while (end >= start && Character.isWhitespace(str.charAt(end))) {
            end--;
        }
        // 截取有效部分
        return str.substring(start, end + 1);
    }

    // 手动实现字符串分割方法
    private static String[] splitString(String str, String delimiter) {
        if (str == null || str.isEmpty() || delimiter == null || delimiter.isEmpty()) {
            return new String[0];
        }
        List<String> parts = new ArrayList<>();
        int start = 0;
        int index = str.indexOf(delimiter, start);
        while (index != -1) {
            parts.add(str.substring(start, index));
            start = index + delimiter.length();
            index = str.indexOf(delimiter, start);
        }
        // 添加最后一部分
        parts.add(str.substring(start));
        return parts.toArray(new String[0]);
    }

    private Class<T> clazz;

    public FastJson2JsonRedisSerializer(Class<T> clazz)
    {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException
    {
        if (t == null)
        {
            return new byte[0];
        }
        return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException
    {
        if (bytes == null || bytes.length <= 0)
        {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);

        return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
    }
}